/**********************************************************
    COPYRIGHT
        KND, Inc. (c) 2011
    CLASS NAME
        platform_pwm.c
    DEPENDENCY

    HISTORY
		10/27/2011, created by Guangxing Liu
**********************************************************/
#include "platform_pwm.h"
#include "platform_config.h"
#include "platform_uart.h"
#include "lpc177x_8x_pwm.h"

extern void Pwm_Change_Freq(platform_pwm_config *pwm_config);

/************************************************************************
	FUNCTION NAME : platform_pwm_init
	INPUTS: 
		none
	OUTPUTS:	
		none
	DESCRIPTION:	
		Platform adc value init
************************************************************************/
void platform_pwm_init(void)
{
	
}

/************************************************************************
	FUNCTION NAME : platform_pwm_device_open
	INPUTS: 
		none
	OUTPUTS:	
		none
	DESCRIPTION:	
		pwm Device Open
************************************************************************/
DeviceHandle platform_pwm_device_open(void)
{
	platform_pwm_app_call* handle = (platform_pwm_app_call*)malloc(sizeof(platform_pwm_app_call));
	if(handle)
	{
		handle->iOpt = Platform_Pwm_App_Call_None;
	}
	return (DeviceHandle)handle;
 }	

/************************************************************************
	FUNCTION NAME : platform_pwm_device_close
	INPUTS: 
		DeviceHandle handle
	OUTPUTS:	
		none
	DESCRIPTION:	
		pwm Device Close
************************************************************************/
int platform_pwm_device_close(DeviceHandle handle)
{
	platform_pwm_app_call* me = (platform_pwm_app_call*)handle;
	if(me)
	{
		free(me);
	}
	return 0;
	
}/************************************************************************
	FUNCTION NAME : platform_pwm_device_ioctl
	INPUTS: 
		DeviceHandle handle, const char *params
	OUTPUTS:	
		none
	DESCRIPTION:	
		pwm Device Control
************************************************************************/
int platform_pwm_device_ioctl(DeviceHandle handle, const char *params)
{
	platform_pwm_app_call* me = (platform_pwm_app_call*)handle;
	
	switch(*params)
	{
		case '0':
			me->iOpt = Platform_Pwm_App_Call_Pwm_Init;
			return 0;
		case '1':
			me->iOpt = Platform_Pwm_App_Call_Pwm_Setpwmvalue;
			return 0;
			
		default:
			platform_printf("ERROR--platform_pwm_device_ioctl unkown params: %s\r\n",params);
			break;
	}

	return -1;
}

/************************************************************************
	FUNCTION NAME :platform_pwm_device_read
	INPUTS: 
		DeviceHandle handle, char *buf, int len
	OUTPUTS:	
		none
	DESCRIPTION:	
		pwm Device Read
************************************************************************/
int platform_pwm_device_read(DeviceHandle handle, void *buf, int len)
{
	platform_pwm_app_call* me = (platform_pwm_app_call*)handle;
	
	if(!me || !buf)
		return -1;
	switch(me->iOpt)
	{
		case 0:			
	         	return 0;
		default:
			platform_printf("ERROR--platform_pwm_device_read unkown params: %s\r\n",me->iOpt);
			break;
	}
	
	return -1;

}

/************************************************************************
	FUNCTION NAME : platform_pwm_device_write
	INPUTS: 
		DeviceHandle handle,  const char *buf, int len
	OUTPUTS:	
		none
	DESCRIPTION:	
		pwm Device Write
************************************************************************/
int platform_pwm_device_write(DeviceHandle handle,  void *buf, int len)
{
	platform_pwm_app_call* me = (platform_pwm_app_call*)handle;
	if(!me || !buf)
		return -1;
	switch(me->iOpt)
	{
		case Platform_Pwm_App_Call_Pwm_Setpwmvalue:
			{
				platform_pwm_config* pwm_config = (platform_pwm_config*)buf;
				
				Pwm_Change_Freq(pwm_config);
			}
			return 0;
		case Platform_Pwm_App_Call_Pwm_Init:
			{
				platform_pwm_config *pwm_config = (platform_pwm_config *)buf;

				Pwm_Conifg(pwm_config);
				
			}
			return 0;
		default:
			platform_printf("ERROR--platform_pwm_device_write unkown params: %s\r\n",me->iOpt);
			break;
	}
	return -1;

}
/************************************************************************
	FUNCTION NAME : platform_init_pwm_device
	INPUTS: 
		none
	OUTPUTS:	
		none
	DESCRIPTION:	
		pwm Device Init
************************************************************************/
void platform_init_pwm_device(void)
{
	DeviceInterface pwm = {
                               platform_pwm_device_open,
                               platform_pwm_device_close,
                               platform_pwm_device_ioctl,
                               platform_pwm_device_read,
                               platform_pwm_device_write
                              };


	hyacinth_install_device(PWM_DEVICE,&pwm);
}

/************************************************************************
	FUNCTION NAME : platform_finit_pwm_device
	INPUTS: 
		none
	OUTPUTS:	
		none
	DESCRIPTION:	
		pwm Device Finit
************************************************************************/
void platform_finit_pwm_device(void)
{
	hyacinth_uninstall_device(PWM_DEVICE);
}

/************************************************************************
	FUNCTION NAME : Pwm_Conifg
	INPUTS: 
		pwm_config
	OUTPUTS:	
		none
	DESCRIPTION:	
		pwm Device Pwm_Conifg
************************************************************************/
int Pwm_Conifg(platform_pwm_config *pwm_config)
{
//	uint8_t pwmChannel;
	PWM_TIMERCFG_Type PWMCfgDat;
	PWM_MATCHCFG_Type PWMMatchCfgDat;
	static char first_run=1;

	if(!pwm_config) return 0;

	/* PWM block section -------------------------------------------- */
	/* Initialize PWM peripheral, timer mode
	 * PWM prescale value = 1 (absolute value - tick value) */

	if(first_run)
	{
		PWMCfgDat.PrescaleOption = PWM_TIMER_PRESCALE_USVAL;
		PWMCfgDat.PrescaleValue = 1;
		PWM_Init(pwm_config->pwm_no, PWM_MODE_TIMER, (void *) &PWMCfgDat);
	}

	switch(pwm_config->pwm_channel)
	{
		case PWM_CHANNEL1:
			#ifdef LPC1754
			// Initialize PWM pin connect p1.18
			PINCON->PINSEL3 |= 0x00000020;	/* PWM1.1 */
			#else
			PINSEL_ConfigPin(1,18,2);
			#endif
			break;
		case PWM_CHANNEL2:
			#ifdef LPC1754
			// Initialize PWM pin connect p1.20
			PINCON->PINSEL3 |= 0x00000200;	/* PWM1.2 */
			#else

			PINSEL_ConfigPin(1,20,2);
			#endif
			break;
		case PWM_CHANNEL3:
			break;
		case PWM_CHANNEL4:
			#ifdef LPC1754
			// Initialize PWM pin connect p1.23
			PINCON->PINSEL3 |= 0x00008000;	/* PWM1.4 */
			#else
			PINSEL_ConfigPin(1,23,2);
			#endif
			break;
		case PWM_CHANNEL5:
			#ifdef LPC1754
			// Initialize PWM pin connect p1.24
			PINCON->PINSEL3 |= 0x00020000;	/* PWM1.5 */

			#else

			PINSEL_ConfigPin(1,24,2);
			#endif
			break;
		case PWM_CHANNEL6:
			break;
			default:
				return 0;					
	}

	if(first_run)
	{

		/* Set match value for PWM match channel 0 = 0xFF, update immediately */
		PWM_MatchUpdate(pwm_config->pwm_no,0, 0xFF, PWM_MATCH_UPDATE_NOW);

		/* PWM Timer/Counter will be reset when channel 1 matching
		 * no interrupt when match
		 * no stop when match */
		PWMMatchCfgDat.IntOnMatch = DISABLE;
		PWMMatchCfgDat.MatchChannel = 0;
		PWMMatchCfgDat.ResetOnMatch = ENABLE;
		PWMMatchCfgDat.StopOnMatch = DISABLE;
		PWM_ConfigMatch(pwm_config->pwm_no, &PWMMatchCfgDat);
	}

	/* Edge setting ------------------------------------ */
	PWM_ChannelConfig(pwm_config->pwm_no, pwm_config->pwm_channel, PWM_CHANNEL_SINGLE_EDGE);
																			 
	/* Match value setting ------------------------------------ */
	PWM_MatchUpdate(pwm_config->pwm_no, pwm_config->pwm_channel, pwm_config->pwm_value, PWM_MATCH_UPDATE_NOW);

	/* Enable PWM Channel Output ------------------------------------ */
	/* Channel 1 */
	PWM_ChannelCmd(pwm_config->pwm_no, pwm_config->pwm_channel, ENABLE);

	if(first_run)
	{

		/* Reset and Start counter */
		PWM_ResetCounter(pwm_config->pwm_no);

		PWM_CounterCmd(pwm_config->pwm_no, ENABLE);

		/* Start PWM now */
		PWM_Cmd(pwm_config->pwm_no, ENABLE);
	}

	first_run =0;

    /* Loop forever */
    return 1;
}


/************************************************************************
	FUNCTION NAME : Pwm_Conifg
	INPUTS: 
		pwm_config
	OUTPUTS:	
		none
	DESCRIPTION:	
		pwm Device Pwm_Conifg
************************************************************************/
void Pwm_Change_Freq(platform_pwm_config *pwm_config)
{
	if(!pwm_config) return;
	/* Match value setting ------------------------------------ */
	PWM_MatchUpdate(pwm_config->pwm_no, pwm_config->pwm_channel, pwm_config->pwm_value, PWM_MATCH_UPDATE_NEXT_RST);
	
}


















